<?php

namespace app\api\v1\controller;

use app\api\v1\validate\auth\login\AliGetMobileValidate;
use app\api\v1\validate\auth\login\AppleLoginValidate;
use app\api\v1\validate\auth\login\LoginByMobileValidate;
use app\api\v1\validate\auth\login\PasswordLoginValidate;
use app\api\v1\validate\auth\login\QQLoginValidate;
use app\api\v1\validate\auth\login\WechatAppLoginValidate;
use app\api\v1\validate\auth\login\WechatLoginValidate;
use app\api\v1\validate\auth\login\WeiboLoginValidate;
use app\api\v1\validate\user\user\ChangePasswordValidate;
use app\common\ApiBase;
use app\common\OsType;
use app\service\AliMobileService;
use app\service\OssService;
use Exception;
use polymerize\auth\service\LoginService;
use polymerize\user\service\UserService;
use support\Redis;
use support\Request;
use support\Response;

class Auth extends ApiBase
{
    /**
     * 阿里云一键登录
     * 三网通手机号码一键登录
     *
     * @param Request $request
     * @return Response
     */
    public function aliGetMobile(Request $request): Response
    {
        $validate = new AliGetMobileValidate();
        if (!$validate->check($request->post())) return $this->apiFailed($validate->getError());

        $accessToken = $request->post('AccessToken', '');
        $ref         = $request->post('ref', '');

        $res = LoginService::getInstance()->aliGetMobile($accessToken, $ref);

        return ($res['code'] == 200) ? $this->apiSuccess($res['data'], '登录成功') : $this->apiFailed($res['msg']);
    }

    /**
     * 手机验证码登录[发送短信验证]
     *
     * @throws Exception
     */
    public function loginByMobile(Request $request): Response
    {
        $validate = new LoginByMobileValidate();
        if (!$validate->check($request->post())) return $this->apiFailed($validate->getError());

        $mobile  = $request->post('mobile', '');
        $smsCode = $request->post('sms_code', '');
        $ref     = $request->post('ref', '');

        $res = LoginService::getInstance()->loginByMobile($mobile, $smsCode, $ref);

        return ($res['code'] == 200) ? $this->apiSuccess($res['data'], '登录成功') : $this->apiFailed($res['msg']);
    }

    /**
     * 账号密码登录
     *
     * @throws Exception
     */
    public function passwordLogin(Request $request): Response
    {
        $validate = new PasswordLoginValidate();
        if (!$validate->check($request->post())) return $this->apiFailed($validate->getError());

        $mobile   = $request->post('mobile', '');
        $password = $request->post('password', '');

        $res = LoginService::getInstance()->passwordLogin($mobile, $password);

        return ($res['code'] == 200) ? $this->apiSuccess($res['data'], '登录成功') : $this->apiFailed($res['msg']);
    }

    /**
     * 微信小程序微信登录
     * /v1/auth/wechatLogin
     *
     * @param Request $request
     * @return Response
     */
    public function wechatAppLogin(Request $request): Response
    {
        $validate = new WechatAppLoginValidate();
        if (!$validate->check($request->post())) return $this->apiFailed($validate->getError());

        $code         = $request->post('code', '');
        $encrypteData = $request->post('encrypte_data', '');
        $iv           = $request->post('iv', '');
        $ref          = $request->post('ref', '');

        $res = LoginService::getInstance()->wechatAppLogin($code, $encrypteData, $iv, $ref);

        return ($res['code'] == 200) ? $this->apiSuccess($res['data'], '登录成功') : $this->apiFailed($res['msg']);
    }

    /**
     * 微信登录
     * /v1/auth/wechatLogin
     *
     * @param Request $request
     * @return Response
     */
    public function wechatLogin(Request $request): Response
    {
        $validate = new WechatLoginValidate();
        if (!$validate->check($request->post())) return $this->apiFailed($validate->getError());

        $code    = $request->post('code', '');
        $state   = $request->post('state', '');
        $ref     = $request->post('ref', '');
        $bindUid = $request->post('bind_uid', 0);

        $res = LoginService::getInstance()->wechatLogin($code, $state, $ref, $bindUid);

        return ($res['code'] == 200) ? $this->apiSuccess($res['data'], '登录成功') : $this->apiFailed($res['msg']);
    }

    /**
     * QQ登录
     * https://paytest.owneweb.com/api/v1/auth/qqLogin
     *
     * @param Request $request
     * @return Response
     */
    public function qqLogin(Request $request): Response
    {
        $validate = new QQLoginValidate();
        if (!$validate->check($request->post())) return $this->apiFailed($validate->getError());

        $token   = $request->post('token', '');
        $ref     = $request->post('ref', '');
        $bindUid = $request->post('bind_uid', 0);

        $res = LoginService::getInstance()->qqLogin($token, $ref, $bindUid);

        return ($res['code'] == 200) ? $this->apiSuccess($res['data'], '登录成功') : $this->apiFailed($res['msg']);
    }

    /**
     * 微博登录
     *
     * @param Request $request
     * @return Response
     */
    public function weiboLogin(Request $request): Response
    {
        $validate = new WeiboLoginValidate();
        if (!$validate->check($request->post())) return $this->apiFailed($validate->getError());

        $token    = $request->post('token', '');
        $weiboUid = $request->post('weibo_uid', 0);
        $ref      = $request->post('ref', '');
        $bindUid  = $request->post('bind_uid', 0);

        $res = LoginService::getInstance()->weiboLogin($token, $weiboUid, $ref, $bindUid);

        return ($res['code'] == 200) ? $this->apiSuccess($res['data'], '登录成功') : $this->apiFailed($res['msg']);
    }

    /**
     * 游客登录
     *
     * @param Request $request
     * @return Response
     */
    public function touristLogin(Request $request): Response
    {
        $uuid = $request->post('uuid', '');
        if (empty($uuid)) return $this->apiFailed('empty uuid');

        $res = LoginService::getInstance()->touristLogin($uuid);

        return ($res['code'] == 200) ? $this->apiSuccess($res['data'], '登录成功') : $this->apiFailed($res['msg']);
    }

    /**
     * Apple登录
     *
     * @param Request $request
     * @return Response
     */
    public function appleLogin(Request $request): Response
    {
        $validate = new AppleLoginValidate();
        if (!$validate->check($request->post())) return $this->apiFailed($validate->getError());

        if ($request->os_type != OsType::OS_TYPE_IOS->value) return $this->apiFailed('请使用IOS设备进行操作');
        $identityToken = $request->post('identityToken', '');
        $ref           = $request->post('ref', '');
        $bindUid       = $request->post('bind_uid', 0);

        $res = LoginService::getInstance()->appleLogin($identityToken, $ref, $bindUid);

        return ($res['code'] == 200) ? $this->apiSuccess($res['data'], '登录成功') : $this->apiFailed($res['msg']);
    }

    /**
     * 阿里云手机验证是否一致
     *
     * @param Request $request
     * @return Response
     */
    public function aliVerifyMobile(Request $request): Response
    {
        //App端SDK获取AccessCode参数值，即Token。
        $accessCode = $request->post('AccessCode', '');
        //手机号。
        $phoneNumber = $request->post('PhoneNumber', '');
        if (empty($accessCode) || empty($phoneNumber)) return $this->apiFailed();

        $ret = AliMobileService::instance()->VerifyMobile($accessCode, $phoneNumber);
        if ($ret['Code'] != 'OK') return $this->apiFailed($ret['Message']);

        $verifyResult = $ret['GateVerifyResultDTO']['VerifyResult'];
        //PASS：一致。REJECT：不一致。UNKNOWN：无法判断。
        return $this->apiSuccess('', $verifyResult);
    }

    /**
     * ossStsToken
     *
     */
    public function ossStsToken(Request $request): Response
    {
        $expire_time = 1;
        $lockKey     = md5(__METHOD__ . $request->uuid);
        $lock        = Redis::setNx($lockKey, 1);
        Redis::expire($lockKey, $expire_time);
        if (!$lock) return $this->apiFailed(MANY_TIMES_REQUEST);
//        $check = $this->checkAesTime();
//        if (is_string($check)) return $this->apiFailed($check);

        try {
            $ret = OssService::instance()->stsToken();
            if (Redis::ttl($lockKey) == -1) Redis::expire($lockKey, $expire_time);             //防止死锁

            $credentials               = $ret['Credentials'] ?? '';
            $credentials['BucketName'] = 'ps-owenweb';
            $credentials['Endpoint']   = 'http://oss-cn-shanghai.aliyuncs.com';
            $credentials['OSS_URL']    = OSS_URL;

            return $this->apiSuccess($credentials);
        } catch (\Throwable $exception) {
            return $this->apiFailed($exception->getMessage());
        }
    }


    /**
     * 手机验证码忘记密码修改密码[发送短信验证]
     *
     */
    public function forgetPassword(Request $request): Response
    {
        $validate = new ChangePasswordValidate();
        if (!$validate->check($request->post())) return $this->apiFailed($validate->getError());

        $mobile          = $request->post('mobile', '');
        $smsCode         = $request->post('sms_code', '');
        $password        = $request->post('password', '');
        $confirmPassword = $request->post('confirm_password', '');
        if ($password != $confirmPassword) return $this->apiFailed('请输入正确的确认密码');

        $res = UserService::getInstance()->forgetPassword($mobile, $smsCode, $password);

        return ($res['code'] == 200) ? $this->apiSuccess() : $this->apiFailed($res['msg']);
    }
}